cover picture sponsor: gleammming.art
你有沒有曾經思考過當你撰寫完 JavaScript 檔案時,為什麼瀏覽器「看」得懂你寫的程式呢?
alert('Hello, JavaScript!');
當你在 VScode 等程式編輯器上打出這段程式碼時,你可能發現 alert
與裡面的 'Hello, JavaScript!'
被上了不同的顏色以作區別,它似乎能夠按著某個規律來識別你所寫的程式,若你不慎打錯字,它還會透過紅色波浪符號提示你的程式碼有問題……
在這個撰寫程式碼的期間我們稱其為編寫時期(Author-time),也就是說,JavaScript 程式碼在這個時候並沒有被執行(Execute)。
然而程式雖然未執行卻有這些效果的出現,最主要是程式編輯器中如:語法檢查(Syntax Check)、語法凸顯(Syntax Highlighting)……等等內建的一些輔助功能,用意主要是來協助你在開發時可能會遇到的各種問題,而這些問題並 不需要等到執行時才發現 ,如此一來你就可以更有效率的撰寫程式與更好的開發體驗。
「那麼……什麼時候電腦才會開始執行 JavaScript 呢?」
實際上,電腦並不懂我們所寫的 JavaScript 程式,而是要透過 JavaScript 引擎(Engine) 即時編譯(Just-in-time) 成電腦能讀懂的語言,而 JavaScript 引擎編譯的過程即是所謂的執行時期(Run time)。
JavaScript 最主要一開始發明的原因便是因為最早的瀏覽器 缺少能夠與使用者立即互動 的功能,僅能 藉由伺服器的回應 來得知一些狀況,但如果像是填寫表單時漏打的情況,在早期你可能要花上一段時間才能得知這項訊息,且當時的網路技術尚未發達,時間跟傳輸的費用成本相當的高。
為了解決這個問題,網景公司讓一名叫做 Brendan Eich 的工程師去著手研究,最後開發出了第一套能應用在瀏覽器的 JavaScript 引擎,使得瀏覽器在即時互動上的體驗顯著的提升,且驚人的是開發的期間僅花了 11 天。
如今,現代的瀏覽器為了更好的使用者體驗,基本上都一定會放入 JavaScript 引擎,來執行頁面中所引入的 JavaScript 檔案。而 JavaScript 引擎目前的生態就如同 F1 賽車中一般,各個引擎所屬的廠商彼此之間不斷互相較勁,而目各家瀏覽器所採用的 JavaScript 引擎如下:
在 F1 賽車領域中,為了避免各家實作上產生不公平等等的議題,會有個國際汽車聯盟(FIA)負責訂定有關於各部位零件的一些規定。同樣地,對於要如何實作 JavaScript 引擎也有個歐洲電腦製造商協會(ECMA 國際)進行標準化,並在 1997 年 6 月時提出 ECMA-262 第一版,而著手開發引擎的工程師們便開始盡量得遵守這項規定,也就代表開發 JavaScript 的工程師們基本上只要遵照著規範所定義出的 ECMAScript 進行開發,基本上就可以在各大瀏覽器中正常運作。(除了某家不合群的瀏覽器……)
額外補充:Node.js 作者即是看見了 JavaScript 引擎的優勢,取用了 V8 引擎並加入一些模組,製成一個不需依賴瀏覽器即可執行的運行環境(Run-time),使得開發者能夠脫離瀏覽器的依賴,開發出更多不需要開啟瀏覽器也能執行的應用程式。
有了引擎之後,我們多少還是會想瞭解引擎究竟是如何將我們的 JavaScript 程式轉為電腦能夠讀懂的程式碼。而接下來我們來看看 JavaScript 程式在瀏覽器中經由 JavaScript 引擎解析時會發生什麼事情:
alert('Hello, JavaScript!');
經由解析器(parser)時,首先會經由 標記化(tokenization),將所有程式碼拆解成單個標記(token);接著再透過 詞法分析(Lexical Analyzer) 分析所有標記的類型與作用:
接著解析器會依據詞法分析所產生的標記的類型,歸類、整理形成一個 抽象語法樹(Abstract Syntax Tree):
最後透過這個抽象語法樹實作出對應的機械碼。
我們在整理一次整個解析流程:
以上便是 JavaScript 引擎編譯時大概所做的事情,當然實際上過程還會涉及更多最佳化的方法來讓整個過程的編譯與執行效能達到更好,但理解到這邊已經對於撰寫 JavaScript 來說很有幫助了!
如果你對於解析器這段過程有興趣的話,你也可以透過這兩個服務試試看:
目標:瞭解 JavaScript 的意義與程式碼大概是如何被執行的。
請試著透過這張樹狀圖或你自製的圖表回想這章節的概念:
在理解完 JavaScript 基本的執行過程後,接下來我們要開始學一些語法,來放到瀏覽器上執行!